package com.xunshibao.message;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.xunshibao.core.dao.page.Pagination;
import com.xunshibao.dao.message.MessageDao;
import com.xunshibao.entity.message.Message;
import com.xunshibao.entity.message.MsgRelation;
import com.xunshibao.entity.message.MsgReply;
import com.xunshibao.entity.user.UserLogin;
import com.xunshibao.service.message.MessageDRO;
import com.xunshibao.util.DateUtil;

@Service("messageService")
@Transactional
public class MessageServiceImpl {
	private MessageDao msgDao;
	
	@Autowired
	public void setMsgDao(MessageDao msgDao) {
		this.msgDao = msgDao;
	}

	public int sendMessage(Long sender, String senderName, List<Long> receivers, String title, String content) {
		if(receivers.contains(sender)) {
			return -5; //收件人不能包括自己
		}
		if (receivers != null && receivers.size() > 0) {
			int now = DateUtil.getNow();

			Message message = null;
			MsgRelation relation = null;
			MsgReply reply = null;
			for (Long receiverId : receivers) {
				message = new Message(sender, senderName, title, content, now, now);
				msgDao.save(message);
				
				relation = new MsgRelation(sender, message.getMsgId(), 1, 1, "1", true, now, null, now);
				msgDao.save(relation);
				relation = new MsgRelation(receiverId, message.getMsgId(), 1, 1, "0", true, now, null, now);
				msgDao.save(relation);
				
				reply = new MsgReply(message.getMsgId(), sender, senderName, title, content, MsgReply.UNREAD, now, now);
				msgDao.save(reply);
			}
		}
		return 0;
	}
	
	public int sendSystemMessage(List<Long> receivers, String title, String content) {
		if (receivers != null && receivers.size() > 0) {
			int now = DateUtil.getNow();

			Message message = null;
			MsgRelation relation = null;
			MsgReply reply = null;
			for (Long receiverId : receivers) {
				message = new Message(0l, "system", title, content, now, now);
				msgDao.save(message);
				
				relation = new MsgRelation(receiverId, message.getMsgId(), 0, 0, "1", false, now, null, now);
				msgDao.save(relation);
			}
		}
		return 0;
	}
	public MessageDRO listInbox(Long userId, int pageNo, int pageSize) {
		MessageDRO dro = new MessageDRO();
		Pagination page = null;
		Map<String, Object> params = new HashMap<String, Object>();
		
//		String sql = "select count(mid) as total from ms_relations where uid=:uid and status=:status union select count(mid) as total from ms_relations where uid=:uid";
//		params.put("uid", userId);
//		params.put("status", "1");
//		
//		List<Map<String, Object>> counts = this.msgDao.findSQL(sql, params);
//		int size = counts.size();
//		int newMsgCnt = 0 ;
//		int totalMsgCnt = -1;
//		if(counts != null && counts.size() > 0) {
//			if(size == 1) {
//				totalMsgCnt = newMsgCnt =((BigInteger) counts.get(0).get("total")).intValue();
//			} else if(size == 2) {
//				newMsgCnt = ((BigInteger) counts.get(0).get("total")).intValue();
//				totalMsgCnt = ((BigInteger) counts.get(1).get("total")).intValue();
//			}
//			dro.setTotal(totalMsgCnt);
//			dro.setNewCnt(newMsgCnt);
//		} else {
//			dro.setStatus(-1);//没有消息
//			return dro;
//		}
		getMsgCnt(userId, false, dro);
		if(dro.getStatus() == -1){//没有消息
			return dro;
		}
		String hql = "select new MsgRelation(r.msgid) from MsgRelation r where r.userid=:userId and r.catid=:catid order by r.createDate";
		params.put("userId", userId);
		params.put("catid", 1);
		//TODO 如果传入的页码数大于总页数，让页码数等于最大页码数
		page = this.msgDao.pageFind(hql, pageNo, pageSize, params);
		List<MsgRelation> relations = (List<MsgRelation>) page.getList(); 
		if(relations != null && relations.size() > 0) {
			dro.setPage(page);
			listMessage(dro, params, relations);
		}
		return dro;
	}
	
	private void getMsgCnt(Long userId, boolean isSystem, MessageDRO dro){
		Map<String, Object> params = new HashMap<String, Object>();
		String sql = "select count(mid) as total from ms_relations where uid=:uid and status=:status and catid=:catid union select count(mid) as total from ms_relations where uid=:uid and catid=:catid";
		if(isSystem) {
			params.put("catid", 0);
		} else {
			params.put("catid", 1);
		}
		params.put("uid", userId);
		params.put("status", "1");
		
		List<Map<String, Object>> counts = this.msgDao.findSQL(sql, params);
		int size = counts.size();
		int newMsgCnt = 0 ;
		int totalMsgCnt = -1;
		
		if(counts != null && counts.size() > 0) {
			if(size == 1) {
				totalMsgCnt = newMsgCnt =((BigInteger) counts.get(0).get("total")).intValue();
			} else if(size == 2) {
				newMsgCnt = ((BigInteger) counts.get(0).get("total")).intValue();
				totalMsgCnt = ((BigInteger) counts.get(1).get("total")).intValue();
			}
			dro.setTotal(totalMsgCnt);
			dro.setNewCnt(newMsgCnt);
			dro.setStatus(0);//没有消息
		} else {
			dro.setTotal(0);
			dro.setNewCnt(0);
			dro.setStatus(-1);//没有消息
		}
	}

	private void listMessage(MessageDRO dro,Map<String, Object> params, List<MsgRelation> relations) {
		String hql;
		List<Long> msgIds = new ArrayList<Long>(relations.size());
		for(MsgRelation r : relations) {
			msgIds.add(r.getMsgid());
		}
		
		hql = "select m from Message m where m.msgId in (:msgIds) order by m.modifiedTime";
		params.clear();
		params.put("msgIds", msgIds);
		List<Message> messages = (List<Message>) this.msgDao.find(hql, params);
		
		dro.getPage().setList(messages);
	}
	
	
	public MessageDRO listSystem(Long userId, int pageNo, int pageSize){
		MessageDRO dro = new MessageDRO();;
		getMsgCnt(userId, true, dro);//取得消息总数
		if(dro.getStatus() == -1){
			return dro;
		}
		
		String hql = "select new MsgRelation(r.msgid) from MsgRelation r where r.userid=:userid and r.catid=:catid";
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("userid", userId);
		params.put("catid", 0);
		Pagination page = this.msgDao.pageFind(hql, pageNo, pageSize, params);
		if(page != null && page.getList() != null && page.getList().size() > 0){
			dro.setPage(page);
			listMessage(dro, params, (List<MsgRelation>)page.getList());
		} 
		return dro;
	}
	
	public List<MsgReply> readMsg(Long userId, Long msgId) {
		Map<String, Object> params = new HashMap<String, Object>();
		
		String hql;
		boolean hasMsg = isMsgOwner(userId, msgId);
		if(!hasMsg) {
			return null;// 没有权限查看不是自己的msg
		}
		params.put("msgId", msgId);
		hql = "select r from MsgReply r where r.msgId=:msgId order by r.createtime desc"; 
		List<MsgReply> replies = (List<MsgReply>) this.msgDao.find(hql, params);
		setReadMsgStatus(msgId,userId);
		return replies;
	}

	private boolean isMsgOwner(Long userId, Long msgId) {
		Map<String, Object> params = new HashMap<String, Object>();
		String hql = "select count(r.relationId) from MsgRelation r where r.msgid=:msgId and r.userid=:userId";
		params.put("msgId", msgId);
		params.put("userId", userId);
		
		Long hasMsg = (Long) this.msgDao.findSingle(hql, params);
		if(hasMsg.intValue() == 0) {
			return false;// 没有权限查看不是自己的msg
		}
		return true;
	}
	
	public List<Message> readSysMessage(Long userId, Long msgId) {
		boolean ismine = isMsgOwner(userId, msgId);
		if(ismine) {
			Map<String, Object> params = new HashMap<String, Object>();
			String hql = "select m from Message m where m.msgId=:msgId";
			params.put("msgId", msgId);
			List<Message> msgs = (List<Message>) this.msgDao.find(hql, params);
			setReadMsgStatus(msgId,userId);
			return msgs;
		}
		return null;
	}
	
	private void setReadMsgStatus(Long msgId, Long uid) {
		String hql = "update MsgRelation r set r.status=:status, r.activedate=:activedate where r.userid=:userid and r.msgid=:msgid";
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("status", "0");
		params.put("activedate", DateUtil.getNow());
		params.put("userid", uid);
		params.put("msgid", msgId);
		this.msgDao.hqlUpdate(hql, params);
	}
	
	public int reply(Long userId, String username, Long msgId, String content) {
		int now = DateUtil.getNow();
		Map<String, Object> params = new HashMap<String, Object>();
		
		//限制回复的权限
		boolean hasMsg = isMsgOwner(userId, msgId);
		if(!hasMsg) {
			return -3;//无权查看
		}
		MsgReply reply = new MsgReply(msgId, userId, username, username, content, MsgReply.UNREAD, now, now);
		boolean result = this.msgDao.save(reply);
		if(!result) {
			return -1;//保存失败
		}
		params.put("content", content);
		params.put("msgId", msgId);
		params.put("now", now);
		String hql = "update Message m set m.content=:content, m.modifiedTime=:now where m.msgId=:msgId";
		int retV = this.msgDao.hqlUpdate(hql, params);
		if(retV == 0) {
			return -2; //更新Message失败
		}
		
		params.clear();
		params.put("status", "2");
		params.put("modifydate", now);
		params.put("msgId", msgId);
		params.put("userId", userId);
		hql = "update MsgRelation r set r.status=:status, r.modifydate=:modifydate where r.msgid=:msgId and r.userid !=:userId";
		retV = this.msgDao.hqlUpdate(hql, params);
		if(retV == 0) {
			return -3; //更新MsgRelation失败
		}
		return 0;
	}
	
	public int delete(Long userid, Long msgId) {
		int result = 0;
		Map<String, Object> params = new HashMap<String, Object>();
		String hql = "select count(*) from MsgRelation r where r.msgid=:msgId";
		params.put("msgId", msgId);
		
		int count =((Long) this.msgDao.findSingle(hql, params)).intValue();
		if(count == 2) {//只有一个方删除
			params.put("userid", userid);
			hql = "delete from MsgRelation r where r.userid=:userid and r.msgid=:msgId";
			result = this.msgDao.hqlUpdate(hql, params);
		} else {
			hql = "delete from MsgRelation r where r.msgid=:msgId";
			result = this.msgDao.hqlUpdate(hql, params);
			
			hql = "delete from Message m where m.msgId=:msgId";
			result += this.msgDao.hqlUpdate(hql, params);
			hql = "delete from MsgReply r where r.msgId=:msgId";
			result += this.msgDao.hqlUpdate(hql, params);
		}
		if(result != -1) {
			return 0;
		} else {
			return -1;//删除失败
		}
	}
	
	public Long getUserIdByName(String username) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("username", username);
		String hql = "select new UserLogin(login.uid, login.username) from UserLogin login where login.username=:username";
		UserLogin login = (UserLogin) this.msgDao.findSingle(hql, params);
		if (login != null) {
			return login.getUid();
		}
		return null;
	}
}

